using System;
using System.Reflection;
using Common.Core;
using Common.Unity.Extensions;
using Microsoft.Practices.ObjectBuilder2;
using Guard=Common.Core.Guard;

namespace Common.Unity.Extensions.Entity
{
	public class DependencyDefaultPropertyValue : DefaultPropertyValueAttributeBase
	{
		public DependencyDefaultPropertyValue( string propertyName ) : base( propertyName )
		{}

		public string BuildKeyName { get; set; }

		protected internal override object GetValue( PropertyInfo property, IBuilderContext context )
		{
			IBuilderContext clone =
				context.CloneForNewBuild( new NamedTypeBuildKey( property.PropertyType, BuildKeyName ), null );
			context.SetBuildSource( null );
			object result = clone.Strategies.ExecuteBuildUp( clone );
			return result;
		}
	}

	public class CurrentTimeDefaultPropertyValue : DefaultPropertyValueAttributeBase
	{
		public CurrentTimeDefaultPropertyValue( string propertyName ) : base( propertyName )
		{}

		protected internal override object GetValue( PropertyInfo property, IBuilderContext context )
		{
			return DateTime.Now;
		}
	}

	public class NewGuidDefaultPropertyValue : DefaultPropertyValueAttributeBase
	{
		public NewGuidDefaultPropertyValue( string propertyName ) : base( propertyName )
		{}

		protected internal override object GetValue( PropertyInfo property, IBuilderContext context )
		{
			return Guid.NewGuid();
		}
	}

	public class DefaultPropertyValueAttribute : DefaultPropertyValueAttributeBase
	{
		readonly string value;

		public DefaultPropertyValueAttribute( string propertyName, object value ) : base( propertyName )
		{
			Microsoft.Practices.Unity.Utility.Guard.ArgumentNotNullOrEmpty( propertyName, "propertyName" );
			Microsoft.Practices.Unity.Utility.Guard.ArgumentNotNull( value, "value" );
			this.value = value.ToString();
		}

		public Type TypeConverterType { get; set; }

		protected internal override object GetValue( PropertyInfo property, IBuilderContext context )
		{
			object result = ConversionHelper.CheckForConversion( value, property, TypeConverterType );
			return result;
		}
	}
}